
/****************************************************************************
**
** Copyright (C) 2004-2008 VATATA.com . All rights reserved.
**
** This file is the part of the Miniutil Poject of VATATA.com.
** Vatata's miniutil library is lightweight and portable (for linux
** and Windows). The C++ Class Library included Threadpool, Dll danymic loading, 
** General socket application model and tcp server, httpserver/servlet, etc. 
** It is a pratical utility disigned for who don't want learn the Big C++ 
** Developing Platform, such as  Boost or ACE.
**
** This file may be used under the terms of the GNU General Public
** License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file.  Alternatively you may (at
** your option) use any later version of the GNU General Public
** License if such license has been publicly approved by VATATA.com.
** (or its successors, if any) and the Miniutil Project Aministrators. 
**
** Please review the following information to ensure GNU General
** Public Licensing requirements will be met:
** http://www.gnu.org/licenses/lgpl.html. If you are unsure which 
** license is appropriate for your use, please review the following 
** information: http://code.google.com/p/miniutil/ or contact 
** http://www.vatata.com.
**
** In addition, as a special exception, VATATA.com, as the sole
** copyright holder for Miniutil Project, grants users of VATATA
** P2P Platform the right to release and package with the related 
** libraries without the source code.
**
** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE. vatata reserves all rights not expressly
** granted herein.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/


#include <stdio.h>
#include "miniutil/runtime.h"
#include "miniutil/dir.h"

#ifdef WIN32
#pragma warning(disable:4996) //ȫ���ص�
#pragma warning(once:4996) //����ʾһ��

#include "winsock2.h"
# include <windows.h>
# include <direct.h>
#include "shlobj.h" 

#elif defined (__APPLE__)

#include <Processes.h>

#else

#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <dirent.h>

#endif


namespace miniutil
{
    namespace runtime
    {

        string & getModuleName()
        {
	        static string exeName;
        	
	        if ( exeName.length() >  0 )
		        return exeName;

        #ifdef WIN32
	        char buf[MAX_PATH+1];
	        DWORD size = ::GetModuleFileName( NULL,  buf, MAX_PATH );

	        for( unsigned int i=0; i< size; i++ )
		        if ( buf[i] == '\\' ) buf[i] = '/';

	        buf[size] = 0;
	        exeName = buf;

	#elif defined (__APPLE__)
                ProcessSerialNumber psn;
                FSRef fsRef;
                if (  noErr == GetCurrentProcess( &psn ) 
                   && noErr == GetProcessBundleLocation(&psn, &fsRef) )
                {
                    char buf[ 10240 ];
                    if ( noErr == FSRefMakePath( &fsRef, (UInt8 *)buf, 10200 ) )
                        exeName = buf;
                }
        #else
            // Linux only
	        char exePath[MAX_PATH+1];
	        char fullPath[MAX_PATH+1];
	        sprintf(exePath,"/proc/%d/exe",getpid());
	        int size = readlink(exePath,fullPath,MAX_PATH );
            if ( size > 0 )
                fullPath[size] = 0;
            else
                exeName = "-INVALIDPATH-";

	        exeName = fullPath;
        #endif
	        return exeName;
        }

        string & getModuleDir()
        {
	        static string exeDir;

	        if ( exeDir.length() > 0 )
		        return exeDir;

	        string & exeName = getModuleName();

	        string::size_type lastsep = exeName.find_last_of( "\\/" );
	        if ( lastsep != string::npos )
		        exeDir = exeName.substr(0, lastsep+1 );

	        return exeDir;
        }

        string & getModuleBaseName()
        {
	        static string baseName;

	        if ( baseName.length() > 0 )
		        return baseName;

	        string & exeName = getModuleName();

            string::size_type lastdot = exeName.find_last_of( "." );
            if ( lastdot == string::npos )
            {
                baseName = exeName;
                return baseName;
            }

	        string::size_type lastsep = exeName.find_last_of( "\\/" );

	        if ( lastsep != string::npos && lastsep > lastdot )
            {
                baseName = exeName;
                return baseName;
            }

	        baseName = exeName.substr(0, lastdot );
	        return baseName;
        }

        string getCurrentDir()
        {
	        char buf[MAX_PATH+1];

	        ::getcwd( buf, MAX_PATH );
        #ifdef WIN32
	        size_t size = strlen(buf);
	        for(unsigned int i=0; i< size; i++ )
		        if ( buf[i] == '\\' ) buf[i] = '/';
        #endif

	        return string(buf);
        }

		//get absolute path by the path where the execute exist..
        string  getAbsolutePathByModule( const string & path )
        {
	        if ( path[0] == '/' )
		        return path;
        #ifdef WIN32
			if ( path[1] == ':' )
		        return path;

	        string npath = path;
	        for(unsigned int i=0; i<npath.length(); i++ )
		        if ( npath[i] == '\\' ) npath[i] = '/';
	        string mdir = getModuleDir();
	        mdir += npath;
        #else
	        string mdir = getModuleDir();
	        mdir += path;
        #endif

	        return mdir;
        }

		//get absolute path by the current path... ??
        string  getAbsolutePathByCwd( const string & path )
        {
	        if ( path[0] == '/' )
		        return path;
        #ifdef WIN32
			if ( path[1] == ':' )
		        return path;

	        string npath = path;
	        for(unsigned int i=0; i<npath.length(); i++ )
		        if ( npath[i] == '\\' ) npath[i] = '/';
	        string mdir = getCurrentDir();
	        mdir += "/";
	        mdir += npath;
        #else
	        string mdir = getCurrentDir();
	        mdir += "/";
	        mdir += path;
        #endif

	        return mdir;
        }
        string  getAppDataPath()
        {
        #ifdef WIN32
            char          szDir[MAX_PATH];

            if(SUCCEEDED( SHGetSpecialFolderPath(NULL, szDir, CSIDL_APPDATA, TRUE )))
            {
		        return szDir;
            }
	        else if ( ::getenv("APPDATA") != NULL )
	        {
		        return ::getenv("APPDATA");
	        }
        #endif
	        char * p_home = ::getenv("HOME");
	        if ( p_home == NULL )
		        return ".";

	        std::string app_data = p_home;
	        app_data += "/.appdata";

            miniutil::dir::mkdir( app_data.c_str() );

	        return app_data;
        }

    }
}
